package cn.hicard.risk.action.webpay;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import cn.hicard.risk.common.Constant;
import cn.hicard.risk.entity.BdTradefileinfo;
import cn.hicard.risk.report.ReportTemplet;
import cn.hicard.risk.service.webpay.TransMonitorService;


/**
 * 前置交易监控FLEX调用的类
 * @author yangzhou
 *
 */
public class TransMonitorFlex {
	private static Logger logger = Logger.getLogger(Constant.LOGGER_MAIN);	
	private TransMonitorService transMonitorService;
	
	private Map<String, String> channelMap = new HashMap<String, String>();
	private Map<String, String> transTypeMap = new HashMap<String, String>();
	private Map<String, String> unionRespCodeMap = new HashMap<String, String>();
	private Map<String, String> quickRespCodeMap = new HashMap<String, String>();
	
	public TransMonitorFlex(){
		channelMap.put("1001", "广银联");
		channelMap.put("1003", "宁波银联");
		channelMap.put("1007", "杭州银联");
		channelMap.put("1009", "福建银联");
		channelMap.put("2001", "快钱");
		channelMap.put("1017", "易宝");
		
		transTypeMap.put("0200", "消费");
		transTypeMap.put("0400", "冲正");
		
		
		unionRespCodeMap.put("00", "承兑或交易成功 A 承兑或交易成功 交易成功");
		unionRespCodeMap.put("01", "查发卡行 C 查发卡行 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("02", "查发卡行的特殊条件 C 可电话向发卡行查询 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("03", "无效商户 C 商户需要在银行或中心登记 商户未登记"); 
		unionRespCodeMap.put("04", "没收卡 D 操作员没收卡 没收卡，请联系收单行"); 
		unionRespCodeMap.put("05", "不予承兑 C 发卡不予承兑 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("06", "出错 E 发卡行故障 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("07", "特殊条件下没收卡 D 特殊条件下没收卡 没收卡，请联系收单行"); 
		unionRespCodeMap.put("09", "请求正在处理中 B 重新提交交易请求 交易失败，请重试"); 
		unionRespCodeMap.put("10", "部分承兑 A 部分金额批准，请收取余额 交易成功，但为部分承兑"); 
		unionRespCodeMap.put("12", "无效交易 C 发卡行不支持的交易 交易失败，请重试"); 
		unionRespCodeMap.put("13", "无效金额 B 金额为0 或太大 交易金额超限，请重试"); 
		unionRespCodeMap.put("14", "无效卡号 B 卡种未在中心登记或读卡号有误 无效卡号，请联系发卡行"); 
		unionRespCodeMap.put("15", "无此发卡行 C 此发卡行未与中心开通业务 此卡不能受理"); 
		unionRespCodeMap.put("19", "重新送入交易 C 刷卡读取数据有误，可重新刷卡 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("20", "无效应答 C 无效应答 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("21", "不做任何处理 C 不做任何处理 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("22", "怀疑操作有误 C POS状态与中心不符，可重新签到 操作有误，请重试"); 
		unionRespCodeMap.put("23", "不可接受的交易费 C 不可接受的交易费 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("25", "未能找到文件上记录 C 发卡行未能找到有关记录 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("30", "格式错误 C 格式错误 交易失败，请重试"); 
		unionRespCodeMap.put("31", "银联不支持的银行 C 此发卡方未与中心开通业务 此卡不能受理"); 
		unionRespCodeMap.put("33", "过期的卡 D 过期的卡，操作员可以没收 过期卡，请联系发卡行"); 
		unionRespCodeMap.put("34", "有作弊嫌疑 D 有作弊嫌疑的卡，操作员可以没收 没收卡，请联系收单行"); 
		unionRespCodeMap.put("35", "受卡方与安全保密部门联系 D 有作弊嫌疑的卡，操作员可以没收 没收卡，请联系收单行"); 
		unionRespCodeMap.put("36", "受限制的卡 D 有作弊嫌疑的卡，操作员可以没收 此卡有误，请换卡重试"); 
		unionRespCodeMap.put("37", "受卡方呼受理方安全保密部门(没收卡) D 有作弊嫌疑的卡，操作员可以没收 没收卡，请联系收单行 "); 
		unionRespCodeMap.put("38", "超过允许的PIN试输入 D 密码错次数超限，操作员可以没收 密码错误次数超限"); 
		unionRespCodeMap.put("39", "无此信用卡账户 C 可能刷卡操作有误 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("40", "请求的功能尚不支持 C 发卡行不支持的交易类型 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("41", "丢失卡 D 挂失的卡， 操作员可以没收 没收卡，请联系收单行"); 
		unionRespCodeMap.put("42", "无此账户 B 发卡行找不到此账户 交易失败，请联系发卡方"); 
		unionRespCodeMap.put("43", "被窃卡 D 被窃卡， 操作员可以没收 没收卡，请联系收单行"); 
		unionRespCodeMap.put("44", "无此投资账户 C 可能刷卡操作有误 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("51", "无足够的存款 C 账户内余额不足 余额不足，请查询"); 
		unionRespCodeMap.put("52", "无此支票账户 C 无此支票账户 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("53", "无此储蓄卡账户 C 无此储蓄卡账户 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("54", "过期的卡 C 过期的卡 过期卡，请联系发卡行"); 
		unionRespCodeMap.put("55", "不正确的PIN C 密码输错 密码错，请重试"); 
		unionRespCodeMap.put("56", "无此卡记录 C 发卡行找不到此账户 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("57", "不允许持卡人进行的交易 C 不允许持卡人进行的交易 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("58", "不允许终端进行的交易 C 该商户不允许进行的交易 终端无效，请联系收单行或银联"); 
		unionRespCodeMap.put("59", "有作弊嫌疑 C 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("60", "受卡方与安全保密部门联系 C 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("61", "超出取款金额限制 C 一次交易的金额太大 金额太大"); 
		unionRespCodeMap.put("62", "受限制的卡 C 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("63", "违反安全保密规定 C 违反安全保密规定 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("64", "原始金额不正确 C 原始金额不正确 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("65", "超出消费次数限制 C 超出消费次数限制 超出消费次数限制"); 
		unionRespCodeMap.put("66", "受卡方呼受理方安全保密部门 C 受卡方呼受理方安全保密部门 交易失败，请联系收单行或银联"); 
		unionRespCodeMap.put("67", "捕捉（没收卡） C 捕捉（没收卡） 没收卡"); 
		unionRespCodeMap.put("68", "收到的回答太迟 C 发卡行规定时间内没有回答 交易超时，请重试"); 
		unionRespCodeMap.put("75", "允许的输入PIN次数超限 C 允许的输入PIN次数超限 密码错误次数超限"); 
		unionRespCodeMap.put("77", "需要向网络中心签到 D POS批次与网络中心不一致 请向网络中心签到"); 
		unionRespCodeMap.put("79", "脱机交易对账不平 C POS终端上传的脱机数据对账不平 POS终端重传脱机数据"); 
		unionRespCodeMap.put("90", "日期切换正在处理 C 日期切换正在处理 交易失败，请稍后重试"); 
		unionRespCodeMap.put("91", "发卡行或银联不能操作 C 电话查询发卡方或银联，可重作 交易失败，请稍后重试"); 
		unionRespCodeMap.put("92", "金融机构或中间网络设施找不到或无法达到 C 电话查询发卡方或网络中心，可重作 交易失败，请稍后重试"); 
		unionRespCodeMap.put("93", "交易违法、不能完成 C 交易违法、不能完成 交易失败，请联系发卡行"); 
		unionRespCodeMap.put("94", "重复交易 C 查询网络中心，可重新签到作交易 交易失败，请稍后重试"); 
		unionRespCodeMap.put("95", "调节控制错 C 调节控制错 交易失败，请稍后重试"); 
		unionRespCodeMap.put("96", "系统异常、失效 C 发卡方或网络中心出现故障 交易失败，请稍后重试"); 
		unionRespCodeMap.put("97", "POS终端号找不到 D 终端未在中心或银行登记 终端未登记，请联系收单行或银联"); 
		unionRespCodeMap.put("98", "银联收不到发卡行应答 E 银联收不到发卡行应答 交易超时，请重试"); 
		unionRespCodeMap.put("99", "PIN格式错 B 可重新签到作交易 校验错，请重新签到"); 
		unionRespCodeMap.put("A0", "MAC校验错 B 可重新签到作交易 校验错，请重新签到"); 
		
		quickRespCodeMap.put("00","交易成功");
		quickRespCodeMap.put("01","请联系发卡行，或核对卡信息后重新输入");
		quickRespCodeMap.put("02","请联系快钱公司");
		quickRespCodeMap.put("03","无效商户");
		quickRespCodeMap.put("04","无效终端");
		quickRespCodeMap.put("05","不予承兑，或核对卡信息后重新输入");
		quickRespCodeMap.put("06","出错");
		quickRespCodeMap.put("07","特定条件下没收卡");
		quickRespCodeMap.put("09","请求正在处理中");
		quickRespCodeMap.put("12","无效交易，或核对卡信息后重新输入");
		quickRespCodeMap.put("13","无效金额，交易金额不在许可的范围内，疑问请联系快钱公司");
		quickRespCodeMap.put("14","无效卡号（无此号），或核对卡信息后重新输入");
		quickRespCodeMap.put("15","无此发卡方");
		quickRespCodeMap.put("17","客户取消");
		quickRespCodeMap.put("18","商户保证金对应的可交易额度不足，请联系快钱公司");
		quickRespCodeMap.put("19","您的快钱账户余额不足以进行退货，请充值到快钱账户后，再进行退货操作");
		quickRespCodeMap.put("20","无效响应");
		quickRespCodeMap.put("21","不能采取行动");
		quickRespCodeMap.put("22","故障怀疑");
		quickRespCodeMap.put("23","不可接受的交易费");
		quickRespCodeMap.put("25","找不到原始交易");
		quickRespCodeMap.put("30","格式错误");
		quickRespCodeMap.put("31","不支持该发卡银行");
		quickRespCodeMap.put("32","商户不受理的卡");
		quickRespCodeMap.put("33","过期的卡");
		quickRespCodeMap.put("34","有作弊嫌疑");
		quickRespCodeMap.put("35","请联系快钱公司");
		quickRespCodeMap.put("36","受限制的卡");
		quickRespCodeMap.put("37","风险卡，请联系快钱公司");
		quickRespCodeMap.put("38","超过允许的试输入");
		quickRespCodeMap.put("39","无贷记账户");
		quickRespCodeMap.put("40","请求的功能尚不支持");
		quickRespCodeMap.put("41","挂失卡");
		quickRespCodeMap.put("42","无此账户");
		quickRespCodeMap.put("43","被窃卡");
		quickRespCodeMap.put("44","无此投资账户");
		quickRespCodeMap.put("51","资金不足");
		quickRespCodeMap.put("52","无此支票账户");
		quickRespCodeMap.put("53","无此储蓄卡账户");
		quickRespCodeMap.put("54","过期的卡");
		quickRespCodeMap.put("55","密码错误");
		quickRespCodeMap.put("56","无此卡记录");
		quickRespCodeMap.put("57","不允许持卡人进行的交易");
		quickRespCodeMap.put("58","不允许终端进行的交易");
		quickRespCodeMap.put("59","有作弊嫌疑");
		quickRespCodeMap.put("60","请联系快钱公司");
		quickRespCodeMap.put("61","超出取款转账金额限制");
		quickRespCodeMap.put("62","受限制的卡");
		quickRespCodeMap.put("63","侵犯安全");
		quickRespCodeMap.put("64","原始金额错误");
		quickRespCodeMap.put("65","超出取款次数限制");
		quickRespCodeMap.put("66","请联系快钱公司");
		quickRespCodeMap.put("67","强行受理（要求在自动柜员机上没收此卡）");
		quickRespCodeMap.put("68","无法在正常时间内获得交易应答，请稍后重试");
		quickRespCodeMap.put("75","允许输入密码次数超限");
		quickRespCodeMap.put("76","无效账户");
		quickRespCodeMap.put("80","交易拒绝");
		quickRespCodeMap.put("90","正在日终处理（系统终止一天的活动，开始第二天的活动，交易在几分钟后可再次发送）");
		quickRespCodeMap.put("91","发卡方或交换中心不能操作");
		quickRespCodeMap.put("92","网络暂时无法达到，请稍后重试");
		quickRespCodeMap.put("93","交易违法、不能完成");
		quickRespCodeMap.put("94","重复交易");
		quickRespCodeMap.put("95","核对差错");
		quickRespCodeMap.put("96","系统异常、失效");
		quickRespCodeMap.put("97","ATM/POS 终端号找不到");
		quickRespCodeMap.put("98","交换中心收不到发卡方应答");
		quickRespCodeMap.put("99","密码格式错");
		quickRespCodeMap.put("C0","正在处理中");
		quickRespCodeMap.put("I0","外部交易跟踪编号（如：商户订单号）发生重复");
		quickRespCodeMap.put("I1","请提供正确的持卡人姓名，必须与申请信用卡时的姓名一致");
		quickRespCodeMap.put("I2","请提供正确的验证码（CVV2），验证码在卡背面签名栏后的三位数字串");
		quickRespCodeMap.put("I3","请提供正确的证件号码，必须与申请信用卡时的证件号码一致");
		quickRespCodeMap.put("I4","请提供正确的卡有效期，卡有效期是在卡号下面的4位数字");
		quickRespCodeMap.put("I5","超出持卡人设置的交易限额，请持卡人联系发卡银行调高限额");
		quickRespCodeMap.put("I6","无效证件类型");
		quickRespCodeMap.put("I8","不支持的报价币种");
		quickRespCodeMap.put("I9","银行结帐中，请重试交易");
		quickRespCodeMap.put("AA","中信银行内部系统错误");
		
	}
	
	public void setTransMonitorService(TransMonitorService transMonitorService) {
		this.transMonitorService = transMonitorService;
	}
	/**
	 * 实时交易监控
	 * @param startTime
	 * @param endTime
	 * @param maxTransTime
	 * @return
	 * @throws Exception
	 */
	public List<Map<String, Object>> findList(String startTime, String endTime, String maxTransTime) throws Exception{
		List<Map<String, Object>> resultList1 = transMonitorService.findList(startTime, endTime, maxTransTime);
		List<Map<String, Object>> resultList2 = new ArrayList<Map<String, Object>>();
		
		if(resultList1 != null && resultList1.size() > 0){
			for(int i = 0; i < resultList1.size(); i++){
				String channel = resultList1.get(i).get("channel").toString();
				String transType = resultList1.get(i).get("type").toString();
				String respcode = resultList1.get(i).get("respcode").toString();
				if(!"".equals(channel)){
					resultList2.add(i, resultList1.get(i));
					resultList2.get(i).put("channelDesc", channelMap.get(channel));
					resultList2.get(i).put("typeDesc", transTypeMap.get(transType));
					//区分渠道是快钱还是银联
					if(channel.equals("2001")){
						resultList2.get(i).put("codeDesc", quickRespCodeMap.get(respcode));
					} else {
						resultList2.get(i).put("codeDesc", unionRespCodeMap.get(respcode));
					}
				} else {
					resultList2.get(i).put("channelDesc", "");
					resultList2.get(i).put("typeDesc", "");
					resultList2.get(i).put("codeDesc", "");
				}
			}
		}
		return resultList2;
	}
	/**
	 * 渠道交易成功率统计
	 * @param startTime
	 * @param endTime
	 * @return
	 * @throws Exception
	 */
	public List<Map<String, Object>> successRateStatistics(String startTime, String endTime) throws Exception{
		List<Map<String, Object>> resultList1 = transMonitorService.successRateStatistics(startTime, endTime);
		List<Map<String, Object>> resultList2 = new ArrayList<Map<String, Object>>();
		
		if(resultList1 != null && resultList1.size() > 0){
			for(int i = 0; i < resultList1.size(); i++) {
				String channel = resultList1.get(i).get("channel").toString();
				String failRespcode = resultList1.get(i).get("failRespcode").toString();
				if(!"".equals(channel)){
					resultList2.add(i, resultList1.get(i));
					resultList2.get(i).put("channelDesc", channelMap.get(channel));
					//区分渠道是快钱还是银联
					if(channel.equals("2001")){
						resultList2.get(i).put("codeDesc", quickRespCodeMap.get(failRespcode));
					} else {
						resultList2.get(i).put("codeDesc", unionRespCodeMap.get(failRespcode));
					}
				} else {
					resultList2.add(i, resultList1.get(i));
					resultList2.get(i).put("channelDesc", "");
					resultList2.get(i).put("codeDesc", "");
				}
			}
		}
		return resultList2;
	}
	/**
	 * 查询商户的交易，冲正，查询数据
	 * @param transDate
	 * @param startTime
	 * @param endTime
	 * @param msgcode
	 * @return
	 * @throws Exception
	 */
	public List<Map<String, Object>> exceptionStatistics(String transDate, String startTime, String endTime, String msgcode) throws Exception {
		return transMonitorService.exceptionStatistics(transDate, startTime, endTime, msgcode);
	}
	
	/**
	 * 下载商户的交易，冲正，查询数据
	 * @param startDate
	 * @param endDate
	 * @param merchName
	 * @param merchNo
	 * @param wpmerchNo
	 * @return
	 * @throws Exception
	 */
	public byte[] downloadExceptionStatistics(String transDate, String startTime, String endTime, String msgcode) throws Exception {		
		// 报表模板
		ReportTemplet rt = new ReportTemplet();		
		// 模板的数据源
		List<Map<String, Object>> list = null;		
		try {
			list = transMonitorService.exceptionStatistics(transDate, startTime, endTime, msgcode);
		} catch (Exception e) {
			logger.error("下载报表 发生异常" , e);
			throw e;
		}
		
		String title = "异常统计报表";
		ByteArrayOutputStream os = null;
		if(list != null && list.size() > 0){
			os = rt.createExceptionStatisticsTemplet(list, title, transDate);
		}
		return os.toByteArray();
	}
}
